/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sg.edu.nus.iss.pacman.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Date;

import java.util.Vector;
import sg.edu.nus.iss.pacman.dao.Maze;
import sg.edu.nus.iss.pacman.dao.Score;
import sg.edu.nus.iss.pacman.dao.UserProfile;

/**
 * An IO utility class.
 * @author fredy
 */
public class IOUtils
{
    private IOUtils()
    {
        // Prevent instantiation.
    }

    /**
     * Coverts from bytes to UserProfile.
     * @param bytes the bytes
     * @return the UserProfile
     */
    public static UserProfile convertBytesToUserProfile(byte[] bytes)
    {
        UserProfile userProfile = new UserProfile();
        ByteArrayInputStream bais = null;
        try
        {
            bais = new ByteArrayInputStream(bytes);
            DataInputStream dis = new DataInputStream(bais);
            userProfile.setName(dis.readUTF());
            userProfile.setGender(dis.readInt());
            userProfile.setEmail(dis.readUTF());
            userProfile.setDob(new Date(dis.readLong()));
            int size = dis.readInt();
            Vector scores = new Vector();
            for (int i = 0; i < size; i++)
            {
                Score score = new Score();
                score.setMapName(dis.readUTF());
                score.setScore(dis.readInt());
                scores.addElement(score);
            }
            userProfile.setScores(scores);
        }
        catch (IOException ex)
        {
            throw new RuntimeException(ex.getMessage());
        }
        finally
        {
            try
            {
                bais.close();
            }
            catch (IOException ex)
            {
                ex.printStackTrace();
                throw new RuntimeException(ex.getMessage());
            }
        }
        return userProfile;
    }

    /**
     * Converts from UserProfile to bytes.
     * @param userProfile the UserProfile
     * @return the bytes
     */
    public static byte[] convertUserProfileToBytes(UserProfile userProfile)
    {
        byte[] data = null;
        ByteArrayOutputStream baos = null;
        try
        {
            baos = new ByteArrayOutputStream();
            DataOutputStream dos = new DataOutputStream(baos);
            dos.writeUTF(userProfile.getName());
            dos.writeInt(userProfile.getGender());
            dos.writeUTF(userProfile.getEmail());
            dos.writeLong(userProfile.getDob().getTime());
            dos.writeInt(userProfile.getScores().size());
            Vector scores = userProfile.getScores();
            for (int i = 0; i < scores.size(); i++)
            {
                Score score = (Score) scores.elementAt(i);
                dos.writeUTF(score.getMapName());
                dos.writeInt(score.getScore());
            }
            data = baos.toByteArray();
        }
        catch (IOException ex)
        {
            ex.printStackTrace();
            throw new RuntimeException(ex.getMessage());
        }
        finally
        {
            try
            {
                baos.close();
            }
            catch (IOException ex)
            {
                ex.printStackTrace();
                throw new RuntimeException(ex.getMessage());
            }
        }
        return data;
    }
    
    /**
     * Converts Maze to array of bytes
     * @param maze maze
     * @return array of bytes
     */
    public static byte[] convertMazeToBytes(Maze maze) {
    	byte[] data = null;
    	
    	ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    	DataOutputStream dos = new DataOutputStream(baos);
    	
    	try {			
			dos.writeUTF(maze.getMazeName());
			
			int[][] map = maze.getMap();
			
			dos.writeInt(map.length); //row
			dos.writeInt(map[0].length); //columns
			
			for (int i=0; i<map.length; i++) {
				for (int j=0; j<map[i].length; j++) {
					int value = map[i][j];
					dos.writeInt(value);
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		} finally {
			try {
				dos.close();
				baos.close();
			} catch (IOException e) {				
				e.printStackTrace();
				throw new RuntimeException(e.getMessage());
			}
		}
    	
    	data = baos.toByteArray();
    	return data;
    }
    
    /**
     * Converts from bytes to Maze
     * @param bytes the bytes
     * @return the Maze
     */
    public static Maze convertBytesToMaze(byte[] bytes)
    {
        Maze maze = new Maze();
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);                 
        DataInputStream dis = new DataInputStream(bais);
        
        try {
			maze.setMazeName(dis.readUTF());
			
			int row = dis.readInt();
			int column = dis.readInt();
			
			int[][] map = new int[row][column];
			
			for (int i=0; i<row; i++) {
				for (int j=0; j<column; j++) {
					map[i][j] = dis.readInt();
				}
			}
			maze.setMap(map);
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		} finally {
			try {
				dis.close();
				bais.close();
			} catch (IOException e) {
				e.printStackTrace();
				throw new RuntimeException(e.getMessage());
			}
        
        }
        
        return maze;
    }
}
